use ifun_grep;
use std::collections::HashMap;
// use ferris_says::say;
// use regex::Regex;
// use std::io::{stdout, BufWriter};
#[derive(Debug)]
struct User {
    name: String,
    age: i32,
    email: String,
    id: u64,
    gender: Gender,
}

impl User {
    fn getAgeDesc(&self) -> &str {
        if self.age > 50 {
            return "中年";
        } else if self.age > 30 {
            return "壮年";
        } else if self.age > 18 {
            return "青年";
        }

        return "少年";
    }
    fn admin(user: (String, i32, String, u64, Gender)) -> Self {
        Self {
            name: user.0,
            age: user.1,
            email: user.2,
            id: user.3,
            gender: user.4,
        }
    }
}

#[derive(Debug)]
// enum Gender {
//     Boy,
//     Girl,
// }
enum Gender {
    Boy(String, i32),
    Girl(String, i32),
}

impl Gender {
    fn getHobby(&self) {
        // 这里可以返回男孩、女孩不同的爱好选项
        print!("hobby")
    }
}

// struct Color(i32, i32, i32);

#[derive(Debug)]
enum Color {
    Red(String),
    Green(u32, u32, u32),
    Yellow(u32, u32, u32, u8),
}
/**
 * 泛型定义函数
 */
fn largest<T: std::cmp::PartialOrd>(list: &[T]) -> &T {
    let mut large = &list[0];

    for val in list {
        if val > large {
            large = val;
        }
    }

    large
}

struct Size<T> {
    width: T,
    height: T,
}

enum Status<T, U> {
    YES(T),
    NO(U),
}

impl<T> Size<T> {
    fn width(&self) -> &T {
        &self.width
    }
}
impl Size<u8> {
    fn height(&self) -> &u8 {
        &self.height
    }
}

pub trait Log {
    fn log(&self) -> String;
}

impl<T: std::fmt::Debug> Log for Size<T> {
    fn log(&self) -> String {
        let str = format!("{:?}-{:?}", &self.width, &self.height);
        println!("变更值：{str}");
        str
    }
}
fn main() {
    // let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
    // println!("Did our date match? {}", re.is_match("2014-01-01"));
    // println!("Hello, world!");
    // let stdout = stdout();
    // let message = String::from("Hello fellow Rustaceans!");
    // let width = message.chars().count();

    // let mut writer = BufWriter::new(stdout.lock());
    // say(message.as_bytes(), width, &mut writer).unwrap();
    let age = b'A';
    print!("{age}");
    {
        let age = 34;
        print!("{age}");
    }
    print!("{age}");

    let num: i16 = -1_000;
    print!("{num}");
    let age: i8 = 0b1100;
    print!("{age}");

    let num = 3.4231;
    print!("{num}");

    let value = 9 / 7;
    print!("{value}");

    // let bool = true;

    let char = 'a';
    print!("{char}");

    let tup: (i8, u16, i64) = (54, 500, 1000);

    // 通过结构取值
    let (a, b, c) = tup;
    print!("{a}-{b}-{c}");
    // 通过下表直接读取
    let a = tup.0;
    let b = tup.1;
    print!("{a}-{b}-{c}");

    let arr: [i32; 4] = [34, 45, 1000005, 67];

    let a = arr[0];
    println!("{a}");

    // user_info(45);

    // let num;
    // let age: i32 = num = 32;

    // println!("num -- {:?}", age);

    // let a = {
    //     let b = 45;
    //     b + 32
    // };
    // println!("{a}");
    let val = user_info(45);

    println!("{val}");

    let bool = false;
    let age = if bool { 20 } else { 34 };

    // let name = "hello world!";
    println!("{age}");

    let mut num = 50;
    let age = loop {
        num -= 5;
        if num < 40 {
            break num + 1;
        }
    };
    println!("{age}");

    let mut count = 0;
    'out_in: loop {
        println!("out");
        let mut num = 10;
        loop {
            println!("{num}");
            if num < 7 {
                break;
            }
            if count == 4 {
                break 'out_in;
            }
            num -= 1;
        }
        count += 1;
    }

    let mut count = 0;
    while count < 5 {
        println!("{count}");
        count += 1;
    }

    let arr = [34, 56, 23, 34];
    for val in arr {
        println!("{val}");
    }

    let mut a = String::from("hboot");

    // print_inf(a);
    // let b = a;
    // let b = a.clone();
    // println!("{}-{}", a, b)

    // let b: usize = print_info(&a);

    // println!("{}-{}", a, b);
    // let b: usize = print_info(&mut a);

    // println!("{}-{}", a, b);
    // print_info();

    // let substr = &a[0..3];
    // let len = a.len();

    // let c = &a[..];
    // print!("{}-{}", substr, c)

    // 整个字符串引用
    print_info(&a[..]);
    // 截取引用
    print_info(&a[1..3]);

    let b = "nice rust";
    // 也可以传递字符串字面值
    print_info(b);

    let a: [i32; 4] = [3, 4, 5, 12];

    let b: &[i32] = &a[1..4];

    // let user = User {
    //     name: String::from("hboot"),
    //     age: 32,
    //     email: String::from("bobolity@163.com"),
    //     id: 3729193749,
    //     gender: Gender::Boy,
    // };
    // let other_user = User {
    //     name: String::from("admin"),
    //     ..user
    // };

    // println!("{}", other_user.email);

    // let color = Color(124, 233, 222);

    let arr = [3, 4, 5, 6];

    println!("{:?}", arr);

    // println!("{:?}", user);
    // dbg!(&user);
    // let str = user.getAgeDesc();
    // dbg!(str);

    // 使用结构体函数实现新实例创建
    // let user_one = User::admin((
    //     String::from("test"),
    //     45,
    //     String::from("123@qq.com"),
    //     452411232,
    //     Gender::Boy,
    // ));

    // dbg!(&user_one);

    // let boy = Gender::Boy(String::from("男孩"), 1);

    // dbg!(&boy, &boy.getHobby());

    let mut num: Option<i32> = None;
    let num1 = 32;
    // 枚举定义的值
    let num2: Option<i32> = Some(32);
    let boy = Gender::Boy(String::from("男孩"), 1);
    dbg!(get_gender_code(boy));

    dbg!(plus_one(num2));

    let num = 10;

    dbg!(plus_two(num));
    dbg!(plus_two(4));

    let mut num = 3;
    if let 3 = num {
        num += 2;
    }
    dbg!(num);

    let v: Vec<i32> = Vec::new();

    let v = vec![3, 5, 6];
    let mut v: Vec<i32> = vec![];

    // 更新值
    v.push(23);
    v.push(4);
    v.push(15);
    v.push(56);
    //  取值
    v.get(2); // 4
    v[2]; // 4

    for i in &v {
        println!("{i}");
    }

    for i in &mut v {
        *i += 5;
        println!("{i}");
    }
    dbg!(v[2]);

    let colors = vec![Color::Red(String::from("red")), Color::Green(0, 255, 0)];
    for i in &colors {
        println!("{:?}", i);
    }

    let mut str = String::new();

    let s = "hboot";
    let str = s.to_string();

    let mut s = String::from("hboot");

    s.push_str(" hello");
    s.push('A');

    dbg!(s);

    let s1 = String::from("hboot");
    let s2 = String::from("hello");

    let s = s1 + &s2; // s1的所有权没有了，s2的所有权仍然存在

    let s1 = String::from("hboot");
    let s2 = String::from(" hello");
    let s3 = String::from(" world");

    let s = format!("{s1}{s2}{s3}");
    dbg!(s, s2);

    let s1 = String::from("hboot");

    for c in s1.chars() {
        println!("{c}");
    }
    for c in s1.bytes() {
        println!("{c}");
    }

    let mut map: HashMap<i32, i32> = HashMap::new();

    map.insert(1, 10);
    // map.insert(String::from("hboot"), 10);

    let mut map = HashMap::new();

    let s = String::from("red");
    map.insert(s, "red");

    let s = map
        .get(&String::from("yellow"))
        .copied()
        .unwrap_or("yellow");
    map.entry(String::from("green")).or_insert("green");
    dbg!("{:?}", map);

    let s1 = String::from("hboot");
    let mut map = HashMap::new();
    for c in s1.chars() {
        let num = map.entry(c).or_insert(0);
        *num += 1;
    }
    dbg!("{:?}", map);

    let v1 = vec![12, 34, 5, 56, 7];
    let v2 = vec![34.23, 12.12, 56.1223, 23.12];

    dbg!(largest(&v1));
    dbg!(largest(&v2));

    let size1: Size<u8> = Size {
        width: 34,
        height: 45,
    };
    let mut size2: Size<f64> = Size {
        width: 34.12,
        height: 45.34,
    };

    size1.height();

    size2.width = 45.111;
    size2.log();

    println!("ifun-grep crate doing...");
    let search = String::from("let");
    let config = ifun_grep::Config {
        search,
        file_path: String::from("hello.txt"),
        ignore_case: true,
    };

    let result = ifun_grep::run(config);

    println!("{}", result.is_ok());
}

fn plus_one(val: Option<i32>) -> Option<i32> {
    match val {
        None => None,
        Some(num) => Some(num + 1),
    }
}
fn plus_two(val: i32) -> i32 {
    match val {
        3 => 3 + 2,
        10 => 10 + 5,
        // other => other - 1,
        _ => -1,
    }
}
fn get_gender_code(gender: Gender) -> i32 {
    // 这里可以返回男孩、女孩不同的爱好选项

    match gender {
        Gender::Boy(label, code) => {
            print!("{}", label);
            code
        }
        Gender::Girl(label, code) => {
            print!("{}", label);
            code
        }
    }
}
// fn getHobby(gender: Gender) -> u8 {
//     // 这里可以返回男孩、女孩不同的爱好选项

//     match gender {
//         Gender::Boy => {
//             print!("男孩");
//             1
//         }
//         Gender::Girl => {
//             print!("女孩");
//             2
//         }
//     }
// }
// fn print_info(str: String) -> (String) {
//     (str)
// }
// 引用变量
// fn print_info(str: &String) -> usize {
//     str.len()
// }

// 可变引用
// fn print_info(str: &mut String) -> usize {
//     str.push_str(",hello");
//     str.len()
// }
// fn print_info() -> String {
//     let str = String::from("hboot");

//     str
// }
fn print_info(str: &str) {
    println!("{}", str);
}
fn user_info(age: u8) -> i64 {
    //
    if age > 50 {
        println!("中年");
    } else if age > 30 {
        println!("壮年");
    } else if age > 18 {
        println!("青年");
    }
    (age + 10).into()
}
